package ru.ifmo.mlarinsky.classificator.providers;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.Set;
import ru.ifmo.mlarinsky.classificator.model.Vector;

import java.util.List;
import ru.ifmo.mlarinsky.classificator.io.InstrumentLoader;
import ru.ifmo.mlarinsky.classificator.math.MathUtil;
import ru.ifmo.mlarinsky.classificator.model.Instrument;
import ru.ifmo.mlarinsky.classificator.model.InstrumentRegister;
import ru.ifmo.mlarinsky.classificator.model.Quote;
import ru.ifmo.mlarinsky.classificator.model.QuoteDate;

/**
 * @author Mikhail Larinskiy
 */
public class ReturnHistoryVectorProvider extends VectorProvider {
    private final String[] dates;

    public ReturnHistoryVectorProvider(List<Instrument> instruments, 
            QuoteDate periodStart, int periodLength)
    {
        super(instruments, periodStart, periodLength);

        this.dates = buildDates();
    }

    public List<Vector> getVectors() {
        List<Vector> vectors = new ArrayList<Vector>();

        for (Instrument instrument : instruments)
            vectors.add(getVector(instrument));
        
        return vectors;
    }

    public String[] getDimensions() {
        String[] dimensions = new String[dates.length - 1];
        System.arraycopy(dates, 1, dimensions, 0, dates.length - 1);
        return dimensions;
    }

    public Vector getVector(Instrument instrument) {
        Double[] values = new Double[dates.length - 1];

        for (int i = 1, length = dates.length; i < length; i++) {
            Quote prevQuote = instrument.getQuote(QuoteDate.valueOf(dates[i - 1]));
            Quote currQuote = instrument.getQuote(QuoteDate.valueOf(dates[i]));

            values[i - 1] = MathUtil.returnRate(prevQuote, currQuote);
        }

        return new Vector(instrument.getSymbol(), getDimensions(), values);
    }

    private String[] buildDates() {
        Set<QuoteDate> quoteDates = instruments.get(0).getQuotes().keySet();
        Iterator<QuoteDate> datesIterator = quoteDates.iterator();
        int counter = periodLength;

        List<String> dateNames = new ArrayList<String>();
        while (datesIterator.hasNext() && counter > 0) {
            QuoteDate date = datesIterator.next();

            if (date.getTime() >= periodStart.getTime()) {
                dateNames.add(date.toString());
                counter--;
            }
        }

        String[] dims = new String[dateNames.size()];
        return dateNames.toArray(dims);
    }

    public static void main(String[] args) {
        testReturnHistoryProvider();
    }

    private static void testReturnHistoryProvider() {
        InstrumentLoader.SAMPLE_INSTRUMENTS.size();
        Instrument ibm = InstrumentRegister.getInstrument("IBM");
        ReturnHistoryVectorProvider provider = new ReturnHistoryVectorProvider(
                Collections.singletonList(ibm), QuoteDate.valueOf("01/15/2011"), 30);

        String[] dims = provider.getDimensions();
        System.out.println("Dimensions (" + dims.length + "):");
        for (String dim : dims) {
            System.out.println(dim);
        }

        System.out.println("\nASSERTION TEST:");
        List<Vector> vectors = provider.getVectors();
        for (Vector vector : vectors) {
            for (int i = 0, length = dims.length; i < length; i++) {
                Quote prevQuote = ibm.getQuote(QuoteDate.valueOf(provider.dates[i]));
                Quote currQuote = ibm.getQuote(QuoteDate.valueOf(provider.dates[i + 1]));
                Double[] values = vector.getValues();

                Double boxedVectorValue = values[i];
                double vectorValue = boxedVectorValue != null ? boxedVectorValue : 123456;
                double testValue = MathUtil.returnRate(prevQuote, currQuote);
                if (vectorValue != testValue) {
                    throw new IllegalStateException("TEST FAILED. Reason: testValue = " +
                            testValue + " vectorValue = " + vectorValue);
                }

                prevQuote = currQuote;
            }
        }

        System.out.println("TEST PASSED");
    }
}
